﻿/******************************************************
* author :  cwj
* email  :  chenwenji_360@live.com 
* history:  created by cwj 2015/8/17 2:47:27 
* clrversion :4.0.30319.42000
******************************************************/

using Machine.DataAccess.Linq;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;

namespace Machine.DataAccess.Operation.SqlServer
{
    class SqlServerDataSchemCreator : DataSchemCreatorBase
    {
        public SqlServerDataSchemCreator(ProviderElement providerElement) : base(providerElement) { }
        protected override string SQL_CreateTable
        {
            get { return string.Format("CREATE TABLE {0}({1} uniqueidentifier PRIMARY KEY)", TABLEARG_NAME, COLUMARG_NAME); }
        }

        protected override string SQL_CreateBasic
        {
            get { return string.Format("ALTER TABLE {0} ADD {1} {2}", TABLEARG_NAME, COLUMARG_NAME, COLUMTYPEARG_NAME); }
        }

        protected override string SQL_CreateRelation
        {
            get
            {
                return string.Format("ALTER TABLE {0} ADD {1}id uniqueidentifier; ALTER TABLE {0} ADD CONSTRAINT {0}_{1}_relation FOREIGN KEY ({1}id) REFERENCES {1}({2})",
                    TABLEARG_NAME, OUTTERTABLE_NAME, OUTTERKEY_NAME);
            }
        }

        public override bool CreateTable(string tableName, string primaryKeyName, string primaryKeyType, bool isAutoKey = false)
        {
            var sql = this.SQL_CreateTable.Replace(TABLEARG_NAME,tableName)
                .Replace(COLUMARG_NAME,primaryKeyName);
            if (isAutoKey)
                sql.Replace("uniqueidentifier", " INT IDENTITY(1,1) ");

            return DataResult.CodeFirstExcuteNonQuery(new Linq.TranslateResult(sql, new DbParameter[0]), this.ProviderElement);
        }

        public override bool CreateBaseType(Type table, System.Reflection.PropertyInfo colum)
        {
            var sql = this.SQL_CreateBasic.Replace(TABLEARG_NAME, table.GetTableName())
                .Replace(COLUMARG_NAME, colum.Name)
                .Replace(COLUMTYPEARG_NAME, this.GetDbType(colum.PropertyType));

            return DataResult.CodeFirstExcuteNonQuery(new Linq.TranslateResult(sql, new DbParameter[0]), this.ProviderElement);
        }

        public override bool CreateFK(string tableName, string columName, string columType, string outterTable, string outterKey)
        {
            var sql = this.SQL_CreateRelation.Replace(TABLEARG_NAME, tableName)
                .Replace(OUTTERTABLE_NAME, outterTable)
                .Replace(OUTTERKEY_NAME, outterKey);

            return DataResult.CodeFirstExcuteNonQuery(new Linq.TranslateResult(sql, new DbParameter[0]), this.ProviderElement);
        }

        protected override string GetDbType(Type type)
        {
            var code = Type.GetTypeCode(type);
            if (type == typeof(Guid)) return "uniqueidentifier";
            switch (code)
            {
                case TypeCode.Boolean:
                    return "bit";
                case TypeCode.SByte:
                case TypeCode.Byte:
                    return "tinyint";
                case TypeCode.Char:
                    return "varchar(max)";
                case TypeCode.DateTime:
                    return "datetime";
                case TypeCode.Decimal:
                    return "money";
                case TypeCode.Double:
                    return "float";
                case TypeCode.UInt16:
                case TypeCode.Int16:
                    return "smallint";
                case TypeCode.UInt32:
                case TypeCode.Int32:
                    return "int";
                case TypeCode.UInt64:
                case TypeCode.Int64:
                    return "bigint";
                case TypeCode.Single:
                    return "real";
                case TypeCode.String:
                    return "varchar(max)";
                //case TypeCode.Object:
                //case TypeCode.Empty:
                //case TypeCode.DBNull:
                default:
                    throw new NotSupportedException("Code first 异常类型");
            }
        }
    }
}
